package com.yswy.app.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.PeriodRuleParams;
import com.alipay.api.request.AlipayUserAgreementQueryRequest;
import com.alipay.api.response.AlipayUserAgreementQueryResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yswy.app.service.*;
import com.yswy.common.utils.DateUtils;
import com.yswy.common.utils.StringUtils;
import com.yswy.common.zfbOrder.AgreementStatusEnums;
import com.yswy.common.zfbOrder.CallbackAgreementResVO;
import com.yswy.common.zfbOrder.ZfbKeyVo;
import com.yswy.common.zfbOrder.ZfbOrderUtil;
import com.yswy.domain.entity.*;
import com.yswy.domain.mapper.AgreementOrderMapper;
import com.yswy.domain.mapper.TgCallBackAgreementLogMapper;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.util.*;

@Service
@Slf4j
public class AgreementOrderServiceImpl extends ServiceImpl<AgreementOrderMapper, AgreementOrder>
        implements AgreementOrderService {

    @Autowired
    private AgreementOrderPayLogService agreementOrderPayLogService ;
    @Autowired
    private PayOrderService payOrderService ;
    @Autowired
    private PayOrderZfbLogService payOrderZfbLogService ;
    @Autowired
    private ZfbPayKeyService zfbPayKeyService ;
    @Autowired
    private PackageManageService packageManageService ;
    @Autowired
    private TgCallBackIdService tgCallBackIdService ;
    @Autowired
    private TgCallBackKsIdService tgCallBackKsIdService;
    @Autowired
    private TgChannleService tgChannleService;
    @Autowired
    private AppUserService appUserService ;
    @Autowired
    private UserDeviceInfoService userDeviceInfoService ;

    @Autowired
    private TgCallBackAgreementLogMapper tgCallBackAgreementLogMapper ;
    @Autowired
    private SysConfigService sysConfigService;

    @Override
    public AgreementOrder addUserAgreementLog(VipPrice vipPrice,
                                              PayOrder payOrder  , ZfbKeyVo zfbKeyVo) {

        PeriodRuleParams periodRuleParams = vipPrice.getPeriodRuleParams() ;

        AgreementOrder agreementOrder = new AgreementOrder() ;
        //用户 Id
        agreementOrder.setUserId(payOrder.getUserId()) ;
        agreementOrder.setOrderId(payOrder.getOrderId());
        agreementOrder.setPayOrderId(payOrder.getId());
        agreementOrder.setAppId(zfbKeyVo.getAppId());
        agreementOrder.setZfbId(zfbKeyVo.getId());
        agreementOrder.setVipId(vipPrice.getId());
        agreementOrder.setCollTime(vipPrice.getCollTime());
        agreementOrder.setCollTimeType(vipPrice.getCollTimeType());
        agreementOrder.setAgreemenPayNum(vipPrice.getAgreemenPayNum());
        agreementOrder.setSingleAmountOne(vipPrice.getAgreemenPriceOne());
        agreementOrder.setAgreemenType(vipPrice.getAgreemenType());
        agreementOrder.setIsDisposable(vipPrice.getIsDisposable());
        //period_type 周期类型，枚举值为DAY和MONTH
        agreementOrder.setPeriodType(periodRuleParams.getPeriodType());
        //period 扣款周期
        agreementOrder.setPeriod(periodRuleParams.getPeriod());
        //execute_time 首次执行时间
        agreementOrder.setExecuteTime(periodRuleParams.getExecuteTime());

        //single_amount 单次扣款最大金额
        Double singleAmount = Double.parseDouble(periodRuleParams.getSingleAmount())*100 ;
        agreementOrder.setSingleAmount(singleAmount.intValue());
        //total_amount 总金额限制
        Double totalAmount = Double.parseDouble(periodRuleParams.getTotalAmount())*100 ;
        agreementOrder.setTotalAmount(totalAmount.intValue());
        //totalPayments 总扣款次数
        agreementOrder.setTotalPayments(periodRuleParams.getTotalPayments().intValue());
        //商户签约号
        agreementOrder.setExternalAgreementNo(payOrder.getExternalAgreementNo());
        agreementOrder.setCreateTime(new Date());
        //status 协议的当前状态。0 create 创建 1. TEMP：暂存，协议未生效过；2. NORMAL：正常；3. STOP：暂停。（只有签约成功才会返回）
        agreementOrder.setStatus(AgreementStatusEnums.create.getCode());
        //status 协议的当前状态。0 create 创建 1. TEMP：暂存，协议未生效过；2. NORMAL：正常；3. STOP：暂停。（只有签约成功才会返回）
        agreementOrder.setStatusType(AgreementStatusEnums.create.getMessage());

        save(agreementOrder);

        return agreementOrder;
    }

    @Override
    public Boolean isAgreementOrder(Long userId) {
        Integer count = count(new LambdaQueryWrapper<AgreementOrder>().eq(AgreementOrder::getUserId ,userId)
                .eq(AgreementOrder::getStatus , 2));
        return count>0?true:false;
    }

    @Override
    public void userAgreementOk(CallbackAgreementResVO callbackAgreementResVO) {
        String externalAgreementNo = callbackAgreementResVO.getExternal_agreement_no();
        String status = callbackAgreementResVO.getStatus();
        AgreementOrder agreementOrder = getOne(new LambdaQueryWrapper<AgreementOrder>().eq(AgreementOrder::getExternalAgreementNo ,externalAgreementNo));
        if (agreementOrder == null) {
            log.info("周期付款回调签约"+externalAgreementNo+"不存在");
            return;
        }
        if (status.equals("UNSIGN")){
            log.info("周期付款回调签约"+externalAgreementNo+"解约");
            agreementOrder.setStatus(AgreementStatusEnums.UNSIGN.getCode());
            agreementOrder.setStatusType(AgreementStatusEnums.UNSIGN.getMessage());
            if (agreementOrder.getUnsignType() == null){
                agreementOrder.setUnsignType(1);
            }
            agreementOrderPayLogService.unAgreementOrderPayLog(agreementOrder.getId());
        }else if (status.equals("NORMAL")){
            log.info("周期付款回调签约"+externalAgreementNo+"正常");
            try {
                //valid_time 用户代扣协议的实际生效时间
                String validTime = callbackAgreementResVO.getValid_time();
                agreementOrder.setValidTime(DateUtils.getSimpleDateFormat(DateUtils.YYYY_MM_DD_HH_MM_SS).parse(validTime));
                String invalidTime = callbackAgreementResVO.getInvalid_time();
                //invalid_time 用户代扣协议的失效时间
                agreementOrder.setInvalidTime(DateUtils.getSimpleDateFormat(DateUtils.YYYY_MM_DD_HH_MM_SS).parse(invalidTime));
                //sign_time 支付宝代扣协议的实际签约时间
                String signTime = callbackAgreementResVO.getSign_time();
                agreementOrder.setSignTime(DateUtils.getSimpleDateFormat(DateUtils.YYYY_MM_DD_HH_MM_SS).parse(signTime));
                String notifyTime = callbackAgreementResVO.getNotify_time();
                agreementOrder.setNotifyTime(DateUtils.getSimpleDateFormat(DateUtils.YYYY_MM_DD_HH_MM_SS).parse(notifyTime));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            userAgreementUnOldOrder(agreementOrder.getUserId() , callbackAgreementResVO.getExternal_agreement_no());

            agreementOrder.setAgreementNo(callbackAgreementResVO.getAgreement_no());
            agreementOrder.setAlipayUserId(callbackAgreementResVO.getAlipay_user_id());
            agreementOrder.setAlipayLogonId(callbackAgreementResVO.getAlipay_logon_id());
            agreementOrder.setCallbackParameter(JSONObject.fromObject(callbackAgreementResVO).toString());
            agreementOrder.setStatus(AgreementStatusEnums.NORMAL.getCode());
            agreementOrder.setStatusType(AgreementStatusEnums.NORMAL.getMessage());
            agreementOrderPayLogService.addAgreementOrderPayLogV2(agreementOrder , 0 , 0);

            try {
                PayOrder payOrder = payOrderService.getOne(new LambdaQueryWrapper<PayOrder>()
                        .eq(PayOrder::getExternalAgreementNo , agreementOrder.getExternalAgreementNo()));
                if (payOrder!= null){
                    //签约回传
                    Boolean isCallBackDisposable = packageManageService.isCallBackDisposable(payOrder.getChannel());
                    if (isCallBackDisposable){
                        tgCallBackAgreementLogMapper.insert(TgCallBackAgreementLog.builder()
                                .agreementOrderId(agreementOrder.getId())
                                .userId(agreementOrder.getUserId())
                                .createTime(new Date())
                                .build());
//                        UserDeviceInfo userDeviceInfo = userDeviceInfoService.getOne(new LambdaQueryWrapper<UserDeviceInfo>()
//                                .eq(UserDeviceInfo::getUserId , payOrder.getUserId()));
//                        AppUser appUser =appUserService.getById(payOrder.getUserId());
//                        //判断用户来源
//                        Integer integer =  tgChannleService.getUserSource(userDeviceInfo, appUser.getCreateIp() , 1);
//                        if (integer == 0){
//                            tgCallBackIdService.callBackPay(userDeviceInfo ,appUser.getCreateIp(), payOrder.getAmount());
//                        }else if (integer == 1){
//                            tgCallBackKsIdService.ksCallBackPay(userDeviceInfo , appUser.getCreateIp(), payOrder.getAmount());
//                        }
                    }

                }
            }catch (Exception er){
                er.printStackTrace();
            }
        }
        updateById(agreementOrder);
    }



    @Override
    public void callBackAgreementOrder() {
        List<TgCallBackAgreementLog>  tgCallBackAgreementLogs = tgCallBackAgreementLogMapper
                .selectList(new LambdaQueryWrapper<TgCallBackAgreementLog>()
                        .eq(TgCallBackAgreementLog::getStatusType , 0)
                        .last("limit  50"));
        Long CallBackTime = 600000l;
        String s = sysConfigService.selectConfigByKey("sys.CallBack.tgCallBackAgreementLog");
        if (StringUtils.isNotEmpty(s)){
            CallBackTime = Long.parseLong(s);
        }

        for (TgCallBackAgreementLog tgCallBackAgreementLog : tgCallBackAgreementLogs){
            AgreementOrder agreementOrder = getById(tgCallBackAgreementLog.getAgreementOrderId());
            log.info("agreementOrder签约状态："+ agreementOrder.getStatusType()+ "创建时间： "+tgCallBackAgreementLog.getCreateTime());
            if (agreementOrder.getStatusType().equals("NORMAL")){
                Date date = new Date();

                if (date.getTime() - tgCallBackAgreementLog.getCreateTime().getTime()>=CallBackTime){
                    tgCallBackAgreementLog.setStatusType(1);
                    tgCallBackAgreementLogMapper.updateById(tgCallBackAgreementLog);
                    AppUser appUser =appUserService.getById(tgCallBackAgreementLog.getUserId());
                    //判断用户来源
                    Integer integer =  tgChannleService.getUserSource(appUser.getId() , appUser.getCreateIp() , 1);
                    if (integer == 0){
                        tgCallBackIdService.callBackPay(appUser.getId() ,appUser.getCreateIp(), 0);
                    }else if (integer == 1){
                        tgCallBackKsIdService.ksCallBackPay(appUser.getId() , appUser.getCreateIp(), 0);
                    }
                }
            }else{
                tgCallBackAgreementLog.setStatusType(1);
                tgCallBackAgreementLogMapper.updateById(tgCallBackAgreementLog);
            }
        }

    }




    @Override
    public void userAgreementUnOldOrder(Long userId , String externalAgreementNo) {
        //判读是否存在周期付款订单
//            status 协议的当前状态。0 create 创建 1. TEMP：暂存，协议未生效过；2. NORMAL：正常；3. STOP：暂停。（只有签约成功才会返回）
        List<AgreementOrder> agreementOrders = list(new LambdaQueryWrapper<AgreementOrder>()
                .eq(AgreementOrder::getUserId , userId)
                .ne(StringUtils.isNotEmpty(externalAgreementNo) , AgreementOrder::getExternalAgreementNo ,externalAgreementNo)
                .eq(AgreementOrder::getStatus ,2  ));
        if (agreementOrders.size()>0){
            //解除扣款协议
            for (AgreementOrder u: agreementOrders) {
                ZfbKeyVo zfbKeyVo = zfbPayKeyService.getZfbKeyVo(u.getZfbId() , null);
                ZfbOrderUtil.AlipayUserAgreementUnsignRequest(zfbKeyVo ,u.getAlipayUserId()
                        , u.getExternalAgreementNo() , u.getAgreementNo());
                u.setUnsignType(0);
            }
            updateBatchById(agreementOrders);
        }
    }


    @Override
    public void callbackAgreement(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Thread.sleep(500);
        Map<String, String> parameters = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : requestParams.entrySet()) {
            String key = entry.getKey();
            String[] values = entry.getValue();
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            parameters.put(key, valueStr);
        }
        log.info("周期付款回调签约参数 parameters is [parameters={}]", parameters);
        CallbackAgreementResVO callbackAgreementResVO = new CallbackAgreementResVO(parameters);
        userAgreementOk(callbackAgreementResVO);
    }




    @Override
    public void zfbCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Thread.sleep(200);
        Map<String, String> parameters = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : requestParams.entrySet()) {
            String key = entry.getKey();
            String[] values = entry.getValue();
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            parameters.put(key, valueStr);
        }
        log.info("应用网关回调parameters is [parameters={}]", parameters);
        String agreement_no = parameters.get("agreement_no");
        if (StringUtils.isNotEmpty(agreement_no)){
            CallbackAgreementResVO callbackAgreementResVO = new CallbackAgreementResVO(parameters);
            userAgreementOk(callbackAgreementResVO);
        }
    }

    @Override
    public void userAgreementUpdateExTime(String memo , String deduct_time, String agreement_no) {
        AgreementOrder agreementOrder = getOne(new LambdaQueryWrapper<AgreementOrder>()
                .eq(AgreementOrder::getAgreementNo , agreement_no));
        if (agreementOrder != null){
            ZfbKeyVo zfbKeyVo = zfbPayKeyService.getZfbKeyVo(agreementOrder.getZfbId() , null);

            ZfbOrderUtil.AlipayUserAgreementExecutionplanModifyRequest(zfbKeyVo,
                    deduct_time ,memo ,  agreement_no );

        }
    }

}
